/*
 Cogumelo v0.1 - INNOTO
Copyright (C) 2010 Innoto Gestión para el Desarrollo Social S.L. <mapinfo@innoto.es>

This program is free software; you can redistribute it and/or
modify it under the2009 terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
USA.
*/

/*
//	 *****	***** *     * *****	  *****	*   *
//	**		*	* * * * * *    *  *	  *	 * *
//	**		*	* *  *  * ** **	  *	  *	  *
//	**		*	* *	    * *    *  *	  *	 * *
//   ******	***** *	    * ******  *****	*   *
*/
var Combox = Class.create({
	
    init: function(selectID){
    	//Ids of related elements
    	this.id = selectID.replace('#', '');
		this.containerid =  this.id+'Combox';
		this.ulid = this.id + '_ul';
		this.selectid = this.id+'_sel';
		
		//DOM objects related to combox
		this.parent = $(selectID);	//<select> tag
    	this.container;				//<div> tag
    	this.list;					//<ul> tag
    	this.select; 				//<button> tag
    	
    	//combox' options & internal use related properties 
    	this.parentOptions = new Array;
    	this.options = new Array;
    	this.display = false;
    	this.keepshown = false;
    	this.selectedindex = 0;
    	this.tabindex = false;
    	
		//insert the container after the <select> tag
    	this.parent.after('<div id="' + this.containerid + '"></div>');
    	this.container = $('#'+this.containerid);
    	this.container.addClass('combox_container');
    	//build combox
    	this.build();
    	
    	//detect tabindex and set it
    	if(this.parent.attr('tabindex')) {
	    	this.tabindex = this.parent.attr('tabindex');
			this.select.attr('tabindex', this.tabindex);
    	}

		//hide parent (<select> tag)
		this.parent.hide();
		//create event observers
    	this.launchEvents();
    },
    
    //
    //  DATA SYNC METHODS
    //
    refresh: function() {
    	this.options = new Array;
	    this.parentOptions = $('#' + this.id + ' option');
	    for(var x=0;x<this.parentOptions.length;x++) {
	    	this.options[x] = new ComboxOption(this.id, this.parentOptions[x]);
	    	if(this.options[x].selected) {
	    		this.selectedindex = x;
	    	}
		}
	},
	
	syncDOM: function() {
		//store <ul> and <button> objects
		this.list = $('#'+this.ulid);
    	this.select = $('#'+this.selectid);
    	//store <li> objects into each comboxOptions
		for(var x=0;x<this.options.length;x++) {
    		this.options[x].list = $('li[index="' + x + '"]');
        }
	},

	add: function(text, value) {
		// add <option> to the parent <select> 
		this.container.html('<select id="temp"><option value="' + value + '">' + text + '</option></select>');
		var temp = $('#temp option');
		this.parent.append(temp.clone());  
		// build combox, launch events
    	this.build();
    	this.launchEvents();
	},

	remove: function(index) {
		// remove <option> from the parent <select>, build combox, launch events		
		$(this.options[index].parent).remove();
    	this.build();
    	this.launchEvents();
	},
	
    setSelected: function(index) {
	    //unselect li previous selected and set new one
		this.options[this.selectedindex].unselect;
		this.options[index].select();
	    //set text and class 
		this.select.html(this.options[index].text);
		this.toggleHover(this.options[this.selectedindex].list, false);
		this.toggleHover(this.options[index].list, true);
		//set new selected index
		this.selectedindex = index;
	},
	
	//
	/* ** DISPLAY METHODS (css&html) ** */
	//
	build: function() {
		//clear container (inner html) and refresh data from the parent <select>
		this.refresh();
    	this.container.html('');
		//create dump of html code
		var dump = '<button type="button" id="' + this.selectid + '" class="combox_select"></button>';
		dump += '<ul id="' + this.ulid + '" class="combox_ul">';
		for(var x=0;x<this.options.length;x++) {
			dump += this.options[x].getHTML();
		}
		dump += '</ul>';
		//insert dump into container & syncronize DOM object data
		this.container.html(dump);
		//set css Styles
		this.setStyles();
		
		//set the default option
		this.setSelected(this.selectedindex);

		//tabindex
		if(this.tabindex)
			this.select.attr('tabindex', this.tabindex);
	},
	
	setStyles: function() {
		//syncronize DOM object with combox properties
		this.syncDOM();
		//set core css styles
    	this.container.css({'display' : 'inline-block', 'position' : 'relative'});
    	this.select.css({'border' : 'none', 'text-align' : 'left'});
    	this.list.css({'position' : 'absolute', 'display' : 'none', 'list-style' : 'none', 'margin' : '0px', 'padding' : '0px'});
    	//calculate & set list position
		var Ypos = parseInt(this.container.css("height")) + parseInt(this.container.css("border-bottom-width")) + parseInt(this.container.css("padding-bottom"));
		var wid = parseInt(this.container.css("width")) - parseInt(this.list.css("border-left-width")) - parseInt(this.list.css("border-right-width"));
		this.list.css({'top' : Ypos+'px', 'left' : '0px', 'width' : wid+'px'});
	},
	//
	/*  ** EVENT & EFECT METHODS ** */
	//
	
	launchEvents: function() {
		var that = this;
		//toggle list visibility
		this.select.bind('click', function(e) {
			that.toggleList(!that.display);
		});
		//hide/show list & select options w/ keyboard like a <select> tag!!
		this.select.bind('keydown', function(e){
			that.keyManagment(e);
		});
		//toggle focus class, hide list when combox loses focus
		this.select.bind('focus blur', function(e) {
			that.select.toggleClass('combox_focus');
			if(e.type == 'blur' && !that.keepshown)
				that.toggleList(false);
			//prevent document scrolling ONLY when combox has focus
			if(e.type == 'focus') {
				$(document).bind('keydown', function(e){
				      if(e.keyCode == 38 || e.keyCode == 40)
				          e.preventDefault();
				});
			}
			else {
				$(document).unbind('keydown');
			}
		});

		//toggle hover class and set "mouse-over-the-combox" detector
		$('#' + this.ulid+ ' li').bind('mouseenter mouseleave', function(e) { 
			var bool = false; 
			if(e.type == 'mouseenter')
				var bool = true;
			that.keepshown = bool;
			that.toggleHover($(this), bool);
		});
		//select options w/ mouse, hide list when it happens & return focus to combox
		$('#' + this.ulid+ ' li').bind('click', function(e) {
			that.setSelected($(this).attr('index'));
			that.toggleList(false);
			that.select.focus();
		});
	},

	keyManagment: function(e) {
		var code;
		if (window.event) code = window.event.keyCode;
		else if (e) code = e.which;
		//alert("code: " + code);
		switch(code) {
			case 40:
				if(e.altKey) {
					//alert('');
					this.toggleList(!this.display);
					break;
				}
				if(this.selectedindex < this.options.length-1) {
					this.setSelected(this.selectedindex+1);
				}
				break;
			case 38:
				if(e.altKey) {
					this.toggleList(!this.display);
					break;
				} 
				if(this.selectedindex != 0) {
					this.setSelected(this.selectedindex-1);
				}
				break;	
		}
	},
	 
	toggleList: function(bol) {
		if(this.display == bol) {
			//not necesary to toggle list
			return;
		}
		if(bol) {
			this.list.fadeIn('fast');
			this.display = true;
		}
		else {
			this.list.fadeOut('fast');
			this.display = false;
		}
	},
	
	toggleHover: function(li, bool) {
		if(bool) {
			this.options[this.selectedindex].list.removeClass('combox_over');
			$(li).addClass('combox_over');
		}
		else {
			$(li).removeClass('combox_over');
		}
	}
});

/* ************* COMBOX OPTION CLASS *********** */
var ComboxOption = Class.create({
	//
	//CONSTRUCTOR
	//
	init: function(id, optionTag){
		//parent id (comboxobject)
		this.comboxid = id;
		//<option> object related (parent)
		this.parent = optionTag;
		//<li> object related
		this.list;
		//text to display
		if(this.parent.text) {
			this.text = this.parent.text;
		}
		else { 
			this.text = this.parent.html();
		}
		//boolean selected
		this.selected = false;
		if(this.parent.selected) {
			this.selectid = true;
		}
		//index (list order)
		this.index = this.parent.index;
	},
	//
	//METHODS
	//
	getHTML: function() {
		var dump = '<li id="' + this.comboxid + this.index + '" index="' + this.index + '">';
		dump += this.text;
		dump += '</li>';
		return dump;
	},
	
	select: function() {
		this.parent.selected = true;
		this.selected = true;
		this.list.addClass("combox_over");
	},
	
	unselect: function() {
		this.parent.selected = false;
		this.selected = false;
		this.list.removeClass("combox_over");
	}
});

